﻿using System;
using System.Runtime.InteropServices;

namespace Btstack
{
    public partial class Bluetooth
    {
        public delegate void BtstackPacketHandlerType(byte type, ushort channel, IntPtr packet, ushort size);
        private delegate void BtstackDataSourceCallbackType(IntPtr ds, BtstackDataSourceEventType e);

        /**
        * Address types
        * @note: BTstack uses a custom addr type to refer to classic ACL and SCO devices
        */
        public enum BdAddrType
        {
            LePublic = 0,
            LeRandom = 1,
            LePrivatFallbackPublic = 2,
            LePrivatFallbackRandom = 3,
            Sco = 0xfc,
            Acl = 0xfd,
            Unknown = 0xfe  // also used as 'invalid'
        }

        // IO Capability Values
        private enum IoCapability
        {
            DisplayOnly = 0,
            DisplayYesNo,
            KeyboardOnly,
            NoInputNoOutput,
            KeyboardDisplay // not used by secure simple pairing
        }

        [Flags]
        private enum BtstackDataSourceEventType
        {
            Pool  = 1 << 0,
            Read  = 1 << 1,
            Write = 1 << 2
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct BtstackDataSourceHandle
        {
            public IntPtr handle;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct BtstackDataSourceType
        {
            private readonly BtstackLinkedItemType item;
            public BtstackDataSourceHandle source;
            public BtstackDataSourceCallbackType process;
            public BtstackDataSourceEventType flags;
        }

        [DllImport("btstack-c.dll", EntryPoint = "btstack_memory_init")]
        private static extern void BtstackMemoryInit();

        [DllImport("btstack-c.dll", EntryPoint = "btstack_run_loop_init")]
        private static extern void BtstackRunLoopInit(IntPtr run_loop);

        [DllImport("btstack-c.dll", EntryPoint = "btstack_run_loop_windows_get_instance")]
        private static extern IntPtr BtstackRunLoopWindowsGetInstance();

        [DllImport("btstack-c.dll", EntryPoint = "btstack_chipset_intel_download_firmware")]
        private static extern void BtstackChipsetIntelDownloadFirmware(IntPtr transport, Action<int> callback);

        [DllImport("btstack-c.dll", EntryPoint = "btstack_run_loop_execute")]
        private static extern void BtstackRunLoopExecute();

        [DllImport("btstack-c.dll", EntryPoint = "btstack_run_loop_enable_data_source_callbacks")]
        private static extern void BtstackRunLoopEnableDataSourceCallbacks(IntPtr ds, BtstackDataSourceEventType e);

        [DllImport("btstack-c.dll", EntryPoint = "btstack_run_loop_set_data_source_handler")]
        private static extern void BtstackRunLoopSetDataSourceHandler(IntPtr ds, BtstackDataSourceCallbackType process);

        [DllImport("btstack-c.dll", EntryPoint = "btstack_run_loop_add_data_source")]
        private static extern void BtstackRunLoopAddDataSource(IntPtr ds);

        [DllImport("btstack-c.dll", EntryPoint = "uuid128_to_str")]
        private static extern IntPtr Uuid128ToStr(IntPtr uuid);

        [DllImport("btstack-c.dll", EntryPoint = "le_device_db_init")]
        private static extern void LeDeviceDbInit();

        private static HciState BtstackEventStateGetState(byte[] packet)
        {
            return (HciState)packet[2];
        }

        public static string Uuid128ToStr(byte[] uuid)
        {
            IntPtr UuidPtr = Marshal.AllocHGlobal(16);
            Marshal.Copy(uuid, 0, UuidPtr, 16);

            var StrPtr = Uuid128ToStr(UuidPtr);

            Marshal.FreeHGlobal(UuidPtr);

            return Marshal.PtrToStringAnsi(StrPtr);
        }
    }
}
